package com.shitou.shitoumember.config;

import com.alibaba.fastjson.JSON;
import com.shitou.shitoucommons.exception.RRException;
import com.shitou.shitoucommons.vo.MessageVo;
import com.shitou.shitoumember.service.MemberExchangeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;


/**
 * class detail:
 *
 * @author 石头人
 */
@SuppressWarnings("all")
@Slf4j
@Component
@ServerEndpoint("/shitou/messaging/{account}")
public class MessagingRoom {

    private static MemberExchangeService exchangeService;

    @Autowired
    public void setExchangeService(MemberExchangeService exchangeService){
        MessagingRoom.exchangeService = exchangeService;
    }

    //concurrent包的线程安全Set，用来存放每个客户端对应的WebSocketServer对象。
    private static ConcurrentHashMap<String, Session> sessionPools = new ConcurrentHashMap<>();


    /**
     * 发送站内信
     * @param session 会话
     * @param message 信息
     */
    public void sendMessage(Session session, String message){
        if ( session != null ){
            synchronized (session) {
                try {
                    session.getBasicRemote().sendText(message);
                } catch (IOException e) {
                    e.printStackTrace();
                    throw new RuntimeException("发送消息时发生了IO异常");
                }
            }
        }
    }


    /**
     * 给单个用户发送站内信
     * @param username 用户名，用以获取用户的session
     * @param message 待发送的消息
     */
    public void sendToSinglePerson(String account, String message){
        Session session = sessionPools.get(account);
        if ( session != null && !StringUtils.isEmpty(message) ){
            // 将消息添加到mysql中
            exchangeService.createExchange(JSON.parseObject(message, MessageVo.class));
            sendMessage(session, message);
        }
    }


    /**
     * 创建站内信
     * @param account
     * @param message
     */
    public void sendMessaging(String account, String message){
        Session session = sessionPools.get(account);
        // 发送站内信
        exchangeService.createMessaging(JSON.parseObject(message, MessageVo.class));
        // 如果用户在线，那么发送消息通知，否则啥也不干
        if ( session != null && !StringUtils.isEmpty(message) ){
            // 创建站内信，将消息添加到mysql中
            sendMessage(session, message);
        }
    }


    /**
     * 群发消息
     * @param message 待发送的消息
     */
    public void broadcast(String message){
        log.info("群发消息");
        if ( !StringUtils.isEmpty(message) ){
            for (Session session : sessionPools.values()) {
                if ( session != null ){
                    sendMessage(session, message);
                }
            }
        }
    }


    /**
     * 连接时自动调用
     * @param session 会话
     * @param account 用户账号
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "account") String account){
        // 将该用户的session加入到session池中
        sessionPools.put(account, session);
    }


    /**
     * 断开连接时调用
     * @param account
     */
    @OnClose
    public void onClose(@PathParam("account") String account){
        // 将该用户的会话从session池中移除
        sessionPools.remove(account);
    }


    /**
     * 有消息发送过来时，调用,如果to为-1，那么进行群发消息,
     *  站内信id不为0， 那么就进行站内信读取
     *  否则就是单独发送
     * @param message
     */
    @OnMessage
    public void onMessage(String message){
        MessageVo messageVo = JSON.parseObject(message, MessageVo.class);
        if (messageVo.getTo() != null && messageVo.getTo().equals("-1") ){
            broadcast(message);

        }else if ( messageVo.getMessagingId() != null && !messageVo.getMessagingId().equals(0) ){
            // 读取站内信,标记已读
            MessageVo messageVoById = exchangeService.getMessageVoById(messageVo.getMessagingId(), Long.valueOf(messageVo.getTo()));

            messageVoById.setMessagingId(messageVo.getMessagingId());
            sendToSinglePerson(messageVo.getTo(), JSON.toJSONString(messageVoById));
        } else  {
            // 创建站内信
            sendMessaging(messageVo.getTo(), message);
            System.out.println("进行了站内信创建");

        }
    }


    /**
     * 错误时调用
     */
    @OnError
    public void onError(Session session, Throwable throwable){
        log.error("发生错误");
        throwable.printStackTrace();
    }

}
